package ar.edu.uade.centroDistribucion.sessionBeans;

import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import ar.edu.uade.centroDistribucion.entities.Articulo;
import ar.edu.uade.centroDistribucion.entities.ItemEnvioATienda;
import ar.edu.uade.centroDistribucion.entities.ItemSolicitudFabricacion;
import ar.edu.uade.centroDistribucion.entities.SolicitudFabricacion;
import ar.edu.uade.centroDistribucion.sessionBeans.administradorSolicitudFabricacion;
import ar.edu.uade.centroDistribucion.valueObjects.ArticuloVO;
import ar.edu.uade.centroDistribucion.valueObjects.SolFabrVO;
import ar.edu.uade.centroDistribucion.valueObjects.VistaEnvTVO;
import ar.edu.uade.centroDistribucion.valueObjects.VistaSolFabrVO;

public @Stateless
class administradorSolicitudFabricacionBean implements
		administradorSolicitudFabricacion {
	@EJB
	private administradorArticulo adminArticulo;
	@EJB
	private administradorEnvioATienda adminEnvioATienda;
	
	@PersistenceContext(unitName="CentroDistribucionTortuguitas")
	private EntityManager manager;

	@SuppressWarnings("unchecked")
	public List<VistaSolFabrVO> iniciarSolicitudFabricacion() {
		Query q = manager.createQuery("SELECT solfabr FROM SolicitudFabricacion solfabr Where solfabr.estado = :param");
		q.setParameter("param", "Nuevo");
		List lsolfabr = q.getResultList();
		
		List<VistaSolFabrVO> lvSolFabr = new ArrayList<VistaSolFabrVO>();
		VistaSolFabrVO vSolFabr = new VistaSolFabrVO();	
		
		try
		{
			for (Object solFab : lsolfabr) {
				for(ItemSolicitudFabricacion itemsolfabr : ((SolicitudFabricacion)solFab).getItems() ){				
					vSolFabr = new VistaSolFabrVO();				
					vSolFabr.setArticulo(itemsolfabr.getArticulo().getReferencia());
					vSolFabr.setDescripcion(itemsolfabr.getArticulo().getDescripcion());
					vSolFabr.setCantAPedir(itemsolfabr.getCantidad() * 2);
					vSolFabr.setPendientesAPedir(adminEnvioATienda.pendientePorArticulo(itemsolfabr.getArticulo().getId()));
					vSolFabr.setStock(itemsolfabr.getArticulo().getStock());
					vSolFabr.setIdSolicitudFabricacion(((SolicitudFabricacion)solFab).getId());
					lvSolFabr.add(vSolFabr);
				}	
			}
		}
		catch (Exception e)
		{
			System.out.println("iniciarSolicitudFabricacion:\n");
			System.out.println(e.getMessage());
			System.out.println(e.getClass());
			System.out.println(e.toString());
		}		
		return lvSolFabr;
	}
	
	
	
	public void Generar(List<SolFabrVO> solFabrs) {
		//Este metodo solo actualiza la cantidad pedida y estado de cada articulo en la solicitud ya creada
		SolicitudFabricacion solFab = null;
		for (SolFabrVO solFabrVO : solFabrs) {
			Query q = manager.createQuery("SELECT solFab FROM SolicitudFabricacion solFab WHERE solFab.id= :param");
			q.setParameter("param", solFabrVO.getRefrerenciaSolFabr());
			solFab = (SolicitudFabricacion)q.getSingleResult();
			for (ItemSolicitudFabricacion item : solFab.getItems()) {
				//busco el item en la lista que trae el VO
				for (ArticuloVO artVO : solFabrVO.getArticulos()) {
					if (item.getArticulo().getReferencia().equals(artVO.getReferencia())) {
						item.setCantidad(artVO.getCantidad());
						item.setEstado("Pendiente");
					}
				}
			}
			//una vez actualizados los items actualizo la solfab
			solFab.setEstado("Pendiente");
			manager.merge(solFab);			
		}
	}


	
	@SuppressWarnings("unchecked")
	public List<Articulo> ObtenerArticulosPendientes() {
		List<Articulo> articulos = null;
		
		try		
			{
				Query q = manager.createQuery("SELECT art FROM Articulo art Where art.stock = 0");
				List lArticulos =  q.getResultList();
				for (int i=0; i< lArticulos.size(); i++)
					articulos.add(((Articulo)lArticulos.get(i)));
			}
			catch (Exception e) {}		
		
		return articulos;
	}
	public void ActualizarPendientes(int idSolicitudFabricacion) {

	}

	public void ActualizarPendientes(int idSolicitudFabricacion,
			Articulo articulo) {
		// TODO Auto-generated method stub

	}



	public void ActualizarPendientes(int idSolicitudFabricacion,
			ArticuloVO articulo) {
		// TODO Auto-generated method stub

	}

	@SuppressWarnings("unchecked")
	public List obtenerSolicitudPendientePorArticulo(Articulo articulo) {

		Query q = manager.createQuery("SELECT s FROM SolicitudFabricacion s "+
				"INNER JOIN s.items i INNER JOIN i.articulo "+
				"WHERE s.estado = 'Pendiente' AND i.articulo.referencia = :param " +
				"ORDER BY s.id");
		q.setParameter("param", articulo.getReferencia());
		
		return q.getResultList();
	}


	//Por que no usamos el id que nos tiene que mandar fabrica?????
	public void actualizarPendientesPorArticulo(String referencia, int cantidad) {
		SolicitudFabricacion solFab = null;
		int remanente = cantidad;
		//Voy a buscar a todas las SolFab que tengan ese articulo pedido
		Articulo art = adminArticulo.ObtenerPorReferencia(referencia);
		List SolicitudesFabricacion =  obtenerSolicitudPendientePorArticulo(art);
		for (Object object : SolicitudesFabricacion) {
			solFab = (SolicitudFabricacion)object;
			//Busco el item de la solfab correspondiente
			for (ItemSolicitudFabricacion item : solFab.getItems()) {
				//Me fijo si esta solicitud tiene todavia pendiente a este articulo o no, por eso la segunda condicion
				if (item.getArticulo().getId() == art.getId() && item.getEstado().equals("Pendiente")) {					
					//actualizo el item de solicitud de fabricacion 
					//Si la cantidad que tengo es menor que la pedida solo actualizo la cantidad pendiente, si la completa cambio el estado,
					//si la supera permito que siga el for de solicitudes (si viene de mas de lo que se pidio no pasa nada, se cancela los solfab)
					if (remanente - item.getCantidad()>=0) {
						//hay de mas o para cubrir el total, actualizo estado
						item.setEstado("Cerrado");
						remanente = remanente - item.getCantidad();
					} else {
						//no hay para cumplir solo actualizo la cantidad que va a esperar
						item.setCantidad(item.getCantidad() - remanente);
						remanente = 0;
					}
					//grabo la solfab con la actualizacion de su item
					manager.merge(solFab);
					
					//se supone que solo actualizo uno de esta lista
					break;
				}
			}			
			//Actualizo el estado de la solfab para cerrarla si es necesario
			revisarEstado(solFab);
			//si no queda mas por actualizar no sigo con el for de solfabs
			if (remanente == 0) {
				break;
			}
		}
		
	}



	private void revisarEstado(SolicitudFabricacion solFab) {
		boolean todosCerrados = true;
		for (ItemSolicitudFabricacion item : solFab.getItems()) {
			if (item.getEstado().equals("Pendiente")) {
				todosCerrados = false;
			}
		}
		if(todosCerrados)
			solFab.setEstado("Cerrado");
		else
			solFab.setEstado("Pendiente");
		
		manager.merge(solFab);
	}
}
